﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Linq;
using System.Data.SqlClient;
using NLog;

namespace CoreLibrary.Sql.Ext {

    public static class DataContextExtension {

        const int BatchSize = 1000;

        public static bool InsertAll<T>(this DataContext context, IEnumerable<T> entities) {
            return InsertAll(context, entities, BatchSize);
        }

        public static bool InsertAll<T>(this DataContext context, IEnumerable<T> entities, int batchSize) {
            var dataTable        = LinqUtil.MapToDataTable(entities);
            var tableAttribute   = LinqUtil.GetTableAttribute<T>();
            var columnProperties = LinqUtil.GetColumnProperties<T>();
            var sqlConnection    = (SqlConnection) context.Connection;
            var sqlTransaction   = sqlConnection.BeginTransaction(IsolationLevel.ReadCommitted);
            using (var bulkCopy = new SqlBulkCopy(sqlConnection, SqlBulkCopyOptions.TableLock, sqlTransaction)) {
                bulkCopy.BatchSize = batchSize;
                bulkCopy.DestinationTableName = tableAttribute.Name;

                foreach (var property in columnProperties) {
                    var column = LinqUtil.GetColumnAttribute(property);
                    if (column != null) {
                        bulkCopy.ColumnMappings.Add(property.Name, column.Name);
                    }
                }

                try {
                    bulkCopy.WriteToServer(dataTable);
                    sqlTransaction.Commit();
                    return true;
                }
                catch (Exception exception) {
                    sqlTransaction.Rollback();
                    LogManager.GetCurrentClassLogger().ErrorException("bulk insert  " + typeof(T).Name + " objects failed - " + exception.Message,
                        exception
                    );
                    return false;
                }
            }
        }

        public static bool RemoveAll<T>(this DataContext context) {
            var tableAttribute = LinqUtil.GetTableAttribute<T>();
            var sql = "DELETE FROM " + tableAttribute.Name;

            var sqlConnection  = (SqlConnection) context.Connection;
            var sqlTransaction = sqlConnection.BeginTransaction(IsolationLevel.ReadCommitted);
            var command = new SqlCommand(sql, sqlConnection, sqlTransaction){
                CommandType = CommandType.Text
            };
            try {
                command.ExecuteNonQuery();
                sqlTransaction.Commit();
                return true;
            }
            catch (Exception exception) {
                sqlTransaction.Rollback();
                LogManager.GetCurrentClassLogger().ErrorException("bulk delete failed - " + exception.Message,exception );
                return false;
            }
            finally {
                command.Dispose();
            }
        }

    }
}
